package edu.upenn.seas.peerreview.smui

import edu.upenn.seas.peerreview.Id


/**
 * Makes decisions on behalf of the Application object. Implementions must
 * define the makeMove and placeShips methods, and may optionally override
 * the additional hooks if any action ought to be taken on other actions in the
 * game.
 */
trait Decider {  
  
  /**
   * @return a list of (Point,Point), each being the start/end point of a ship
   */
  def placeShips(boardSize:Point, shipsSizes:List[Int]) : List[(Point,Point)]
  
  /**
   * @return the Id of the opponent to attack and a Point to fire at
   */
  def makeMove(opps : List[Id] ) : (Id, Point)
  
  /**
   * Upon using a decider, the Application object is expected to call onRegister
   * to notify the decider of its existence. It will provide the decider with 
   * functions to query the player and opponents' boards.
   * 
   * <p>This function is expected to be called only once/upon creation.
   * 
   * <p>The behavior of getOpponentBoard when given an invalid Id is unspecified.
   */
  def onRegister( getMyBoard: () => Board, getOpponentBoard: Id => Board) { }
  
  /**
   * When a new game is started, the Application provides the board size and
   * the opponent set. Multiple games may occur.
   */
  def onNewGame( opponents : List[Id], boardSize : Point) { }
  
  /**
   * Called when an opponent reports s/he has committed to a move this turn.
   */
  def onOpponentMoved(opp:Id) { }
  
  /**
   * Called when someone has fired at you.
   */
  def onBeingFiredAt(from : Id, loc:Point) { }
  
  /**
   * Called when someone has fired at you, but now you know who it was!
   */
  def onFiredAtReport(opp : Id, loc:Point, result: FireResultType) { }
  
  /**
   * Called when opponents' firing results are received.
   */
  def onOpponentFireReport(oppFrom:Id, target:Id, loc:Point, result:FireResultType) { }
  
   /**
   * Called when YOUR firing report comes in.
   */
  def onYourFireReport(target:Id, loc:Point, result:FireResultType) { }
  
   /**
   * Called when you are defeated/gameover.
   */
  def onYourFinish(hits:Int, sinks:Int, kills:Int, hasWon:Boolean) { }
 
  /**
   * Called when a player has been defeated.
   */
  def onPlayerResult(opp:Id, hits:Int, sinks:Int, kills:Int, hasWon:Boolean) { } 
  
  /**
   * Called if a player, that is not you, leaves the game.
   */
  def onPlayerWithdrawal(opp:Id) { }
  
  /**
   * Called when a single game is over.
   */
  def onGameOver() {}
  
  /**
   * Called when the tournament is over.
   */
  def onTournamentOver() {}
}
